package at.fhj.swd.pse.beans;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.jboss.logging.Logger;

import at.fhj.swd.pse.domain.CommunityService;
import at.fhj.swd.pse.entities.Activity;
import at.fhj.swd.pse.entities.Community;

/**
 * 
 * @author Robert Puerer
 * @author Helmut Kopf
 * @author Patrick Groeller
 * 
 */

// @Named and @ManagedBean provides same functionality like @Model
@Model
public class CommunityBean {
	public static String REGISTER = "register:";

	private final Logger log = Logger.getLogger(CommunityBean.class);

	@Inject
	private CommunityService cs;

	@Inject
	private LoginBean login;

	@Named
	private List<Community> communities;

	@Produces
	@Named
	private Community newCommunity;

	private Community currentCommunity;

	public CommunityBean() {

	}

	@PostConstruct
	public void init() {
		this.newCommunity = new Community();
		log.info("CommunityBean.init invoked");
	}

	public Community getCurrentCommunity() {
		log.info("CommunityBean.getCurrentCommunity invoked");

		initCurrentCommunity();

		return this.currentCommunity;
	}

	/**
	 * @brief If the active user is a admin, then return all communities,
	 *        otherwise return only released communities
	 * @return
	 */
	public List<Community> getCommunities() {
		if (login.getLoggedInUser() != null && login.getLoggedInUser().isAdmin()) {
			return cs.getCommunities();
		} else {
			return getReleasedCommunities();
		}
	}

	/**
	 * @brief Return only not released communities ( not released by
	 *        administrator )
	 * @return a list of communities
	 */
	public List<Community> getNotReleasedCommunities() {
		List<Community> returnCommunities = new ArrayList<Community>();
		for (Community community : cs.getCommunities()) {
			if (!community.getReleased()) {
				returnCommunities.add(community);
			}
		}
		return returnCommunities;
	}

	/**
	 * @brief Return only released communities ( released by administrator )
	 * @return a list of communities
	 */
	private List<Community> getReleasedCommunities() {

		List<Community> returnCommunities = new ArrayList<Community>();
		for (Community community : cs.getCommunities()) {
			if (community.getReleased()) {
				returnCommunities.add(community);
			}
		}
		return returnCommunities;
	}

	private void initCurrentCommunity() {
		log.info("CommunityBean.initCurrentCommunity invoked");

		FacesContext context = FacesContext.getCurrentInstance();
		Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();

		if (requestMap != null) {
			log.info("requestMap is not null");
			if (requestMap.containsKey("id")) {
				String sid = (String) requestMap.get("id");
				log.info("id = " + sid);

				int id = Integer.parseInt(sid);

				if (this.currentCommunity != null) {
					if (this.currentCommunity.getID() == id) {
						return;
					}
				}

				this.currentCommunity = this.cs.getCommunity(id);

				if (this.currentCommunity != null) {
					log.info("Current Community found");
				}
			}
		}
	}

	public boolean getIsCurrentUserMember() {
		if (login.getLoggedInUser() == null)
			return false;
		if (this.getCurrentCommunity() == null)
			return false;

		return this.getCurrentCommunity().getMembers().contains(login.getLoggedInUser());
	}

	public String enterCommunity() {
		FacesContext facesContext = FacesContext.getCurrentInstance();

		try {
			cs.addUserToCommunity(login.getLoggedInUser(), getCurrentCommunity());

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "User successfull added to community!", "User successfull added to community!");
			// Message is not shown and
			// facesContext.getExternalContext().getFlash().setKeepMessages(true);
			// doesnt help because Mojarra Version must be > 2.1.14 and we use
			// 2.1.7 because of JBOSS. Maybe we should remember this message via
			// a hidden-field
			facesContext.addMessage("commDetails:name", m);
		} catch (Exception e) {
			String errorMessage = e.getMessage();

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Error while adding user to community!");
			facesContext.addMessage("commDetails:enterCommForm:enter", m);
		}
		log.info("CommunityController.enterCommunity invoked");
		// for reloading the page
		return "communitydetails?id=" + getCurrentCommunity().getID() + "&faces-redirect=true";
	}

	public void releaseCommunity(final Community community) {
		FacesContext facesContext = FacesContext.getCurrentInstance();

		try {
			log.debug("Release community. ID: " + community.getID() + ",Name: " + community.getName());
			cs.releaseCommunity(community);

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Community successfully released!", "Community successfully released!");
			facesContext.addMessage(null, m);
		} catch (Exception e) {
			String errorMessage = e.getMessage();

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Error while releasing community!");
			facesContext.addMessage(null, m);
		}

		log.info("CommunityController.enterCommunity invoked");
	}

	public void register() {
		log.info("register invoked");
		FacesContext facesContext = FacesContext.getCurrentInstance();
		try {

			if (StringUtils.isBlank(newCommunity.getName())) {
				FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please enter a name!", "Please enter a name!");
				facesContext.addMessage(REGISTER + "name", m);
			}

			log.info("community name checked");

			for (Community community : cs.getCommunities()) {
				if (StringUtils.equals(community.getName(), newCommunity.getName())) {
					FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Communityname already exists!", "Communityname already exists!");
					facesContext.addMessage(REGISTER + "name", m);
				}
			}

			log.info("community name doesn't exists");

			if (StringUtils.isBlank(newCommunity.getDescription())) {
				FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please enter a description!", "Please enter a description!");
				facesContext.addMessage(REGISTER + "description", m);
			}

			log.info("community description checked");

			if (StringUtils.isBlank(newCommunity.getTopic())) {
				FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please enter a topicname!", "Please enter a topicname!");
				facesContext.addMessage(REGISTER + "topic", m);
			}

			log.info("community topic checked");

			if (!facesContext.getMessageList().isEmpty()) {
				return;
			}

			log.info("Message list is empty");

			newCommunity.setAdministractor(login.getLoggedInUser());

			log.info("setAdministrator");

			cs.createNewCommunity(newCommunity);

			log.info("after createNewCommunity");

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Community successfully registered!", "Community successfully registered! The community will be released soon by administrator.");
			facesContext.addMessage(REGISTER + "create", m);
			newCommunity = new Community(); // to clear values after
											// registration
			log.info("done");
		} catch (Exception e) {
			log.error(e);
			String errorMessage = e.getMessage();

			FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Error while creating a community!");
			facesContext.addMessage(null, m);
		}
	}
	


	public List<Activity> getActivities() {
		List<Activity> list = this.getCurrentCommunity().getActivities();

		// sort the list by id descending
		Collections.sort(list, descActivityComparator());

		return list;
	}
	
	protected Comparator<Activity> descActivityComparator() {
		return new Comparator<Activity>() {
			@Override
			public int compare(Activity first, Activity second) {
				return ((Integer)second.getId()).compareTo((Integer)first.getId());
			}
		};
	}	

}
